package lt.mii.optimum.components;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import lt.mii.optimum.Start;
import lt.mii.optimum.io.XmlFileOut;

/**
 * Class representing a working week. Contains 5 {@link #Day}s
 * 
 * @author dstrukov
 * 
 */
public class Week implements Cloneable {
	private List<Day> days;



	@Override
	protected Object clone() throws CloneNotSupportedException {

		return super.clone();

	}



	/**
	 * Initializes week and all days. Monday - Friday.
	 */
	private void initWeek() {
		days = new ArrayList<Day>(5);
		days.add(new Day(Days.MONDAY));
		days.add(new Day(Days.WEDNESDAY));
		days.add(new Day(Days.FRIDAY));
		days.add(new Day(Days.TUESDAY));
		days.add(new Day(Days.THURSDAY));
		Collections.sort(days);
	}



	public Week() {
		Iterator<Subject> itii = Start.data.getSubjects().iterator();
		while (itii.hasNext()) {
			Subject subject = itii.next();
			System.out.print(subject.getSubjCode() + " ");
			Start.data.Test(subject);
			Start.data.TestT(subject);
		}
		// Iterator<Subject> itt = Start.data.getSubjects().iterator();
		// while (itt.hasNext()) {
		// Subject subject = itt.next();
		// System.out.print(subject.subjCode + " ");
		// Start.data.Test(subject);
		// Start.data.TestT(subject);
		// }
		// System.out.println("========================");

		initWeek();
		for (int i = 0; i < 5; i++) {

			fillDays();

		}
		Iterator<Day> it = days.iterator();
		while (it.hasNext()) {
			Collections.sort(it.next().getFlows());

		}

		this.output();

		Iterator<Subject> iti = Start.data.getSubjects().iterator();
		while (iti.hasNext()) {
			Subject subject = iti.next();
			System.out.print(subject.getSubjCode() + " ");
			Start.data.Test(subject);
			Start.data.TestT(subject);
		}

		Iterator<Day> dit = days.iterator();
		int teacherW = 0;
		int studW = 0;
		while (dit.hasNext()) {
			Day d = dit.next();
			teacherW += d.TeacherWindows();
			studW += d.StudentWindows();
		}

		System.out.println("Teacher windows violations: " + teacherW);
		System.out.println("Student windows violations: " + studW);
		System.out
				.println("Teacher Day Off Violations: " + WeekOffViolations());
	}



	/**
	 * Adds {@link Flow}s to days <br>
	 * Flows are spread through days evenly.
	 */
	private void fillDays() {

		for (int i = 0; i < 5; i++) {
			boolean flag = true;
			while (flag) {
				Iterator<Day> it = days.iterator();

				while (it.hasNext()) {
					flag = it.next().addFlow(i);

				}

			}
		}
	}



	/**
	 * Prints weeks data to c:/Timesheet.xml
	 */
	public void output() {
		Iterator<Day> it = days.iterator();
		XmlFileOut out = new XmlFileOut("Timesheet.xml", "c:/");

		while (it.hasNext()) {
			Day d = it.next();
			out.startRow();
			out.addTag(d.toString());
			out.endRow();
			d.output(out);
		}

		out.close();

	}



	/**
	 * Calculates ammount of <b>Days Off</b> violations through whole the week.
	 * 
	 * @return Returns <code>int</code> amount of violations.
	 */
	public int WeekOffViolations() {
		int ret = 0;
		Iterator<Day> it = days.iterator();
		while (it.hasNext()) {
			ret += DayOffViolations(it.next());
		}

		return ret;
	}



	/**
	 * Calculates ammount of <b>Days Off</b> violations at a particular
	 * {@link Day}.
	 * 
	 * @param day
	 *            to calculate the <b>Day Off </b> violations.
	 * @return Returns <code>int</code> amount of violations.
	 */
	public int DayOffViolations(Day day) {
		int ret = 0;

		Iterator<Teacher> it = Start.data.getTeachers().iterator();

		while (it.hasNext()) {
			Teacher teach = it.next();
			if (teach.getDaysOff().isEmpty())
				continue;

			if (teach.getDaysOff().contains(day.getDay().getNr())
					&& containsTeacher(day, teach))
				ret++;

		}

		return ret;
	}



	/**
	 * Checks if a particular {@link Teacher} is working on a given {@link Day}
	 * 
	 * @param day
	 *            when to check
	 * @param teach
	 *            to search for
	 * @return <code>true</code> if teacher has at least one lesson that day.
	 */
	public boolean containsTeacher(Day day, Teacher teach) {

		Iterator<Flow> it = day.getFlows().iterator();
		while (it.hasNext()) {
			if (it.next().getPersonList().contains(teach))
				return true;
		}

		return false;
	}

}
